package com.jdrx.sw.sewage.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.jdrx.platform.commons.rest.beans.dto.IdDTO;
import com.jdrx.platform.commons.rest.exception.BizException;
import com.jdrx.sw.sewage.beans.dto.DictClassifyQueryDTO;
import com.jdrx.sw.sewage.beans.dto.DictClassifysQueryDTO;
import com.jdrx.sw.sewage.beans.dto.DictQueryDTO;
import com.jdrx.sw.sewage.beans.dto.base.IdsDTO;
import com.jdrx.sw.sewage.beans.entity.DictClassifyPO;
import com.jdrx.sw.sewage.beans.entity.DictPO;
import com.jdrx.sw.sewage.beans.vo.DictVO;
import com.jdrx.sw.sewage.beans.vo.base.PageVO;
import com.jdrx.sw.sewage.common.constant.Constant;
import com.jdrx.sw.sewage.common.util.Asserts;
import com.jdrx.sw.sewage.common.util.BeanUtils;
import com.jdrx.sw.sewage.dao.DictDao;
import com.jdrx.sw.sewage.service.base.BaseServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.google.common.collect.ImmutableMap.of;

@Service
public class DictServiceImpl extends BaseServiceImpl {

    public static final Logger logger = LoggerFactory.getLogger(DictServiceImpl.class);

    @Autowired
    private DictDao dictDao;
    @Autowired
    private DictClassifyServiceImpl dictClassifyServiceImpl;

    /**
     * 保存字典表对象
     *
     * @param po
     * @throws BizException
     */
    @Transactional(rollbackFor = Exception.class)
    public void insert(DictPO po) throws BizException {
        Asserts.notNull(po, "字典表对象");
        int count = 0;
        try {
            count = dictDao.insert(po);
        } catch (Exception e) {
            logger.error("保存字典表对象失败, po='{}'", po, e);
            throw new BizException("保存字典表对象失败");
        }
        Asserts.check(0 != count, "保存字典表对象失败");
    }

    /**
     * 更新字典表对象
     *
     * @param po
     * @throws BizException
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(DictPO po) throws BizException {
        Asserts.notNull(po, "字典表对象");
        try {
            dictDao.update(po);
        } catch (Exception e) {
            logger.error("更新字典表对象，params='{}'", po, e);
            throw new BizException("更新失败");
        }
    }

    /**
     * 删除workStation对象
     *
     * @param po
     * @throws BizException
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(DictPO po) throws BizException {
        Asserts.notNull(po, "参数");
        try {
            po.setDeleteFlag(Constant.DELETE);
            dictDao.delete(po);
        } catch (Exception e) {
            logger.error("删除字典表对象失败，params='{}'", po, e);
            throw new BizException("删除失败");
        }
    }

    /**
     * 根据参数查询字典表po对象
     *
     * @param parmas
     * @return
     * @throws BizException
     */
    public List<DictVO> findByParams(Map<String, Object> parmas) throws BizException {
        Asserts.notNull(parmas, "查询参数");
        try {
            return dictDao.findByParams(parmas);
        } catch (Exception e) {
            logger.error("查询失败", e);
            throw new BizException("查询失败");
        }
    }

    /**
     * 保存字典表
     *
     * @param vo
     * @throws BizException
     */
    public void save(DictVO vo, Long userId, String token) throws BizException {
        // 校验
        validateDictVO(vo);

        // 校验名称是否重复
        DictPO dictPO = getByParams(of("disName", vo.getDisName(), "classifyId", vo.getClassifyId()), null);
        Asserts.check(Objects.isNull(dictPO), "名称重复");

        // 构造参数
        DictPO po = new DictPO();
        DictClassifyPO dictClassifyPO = dictClassifyServiceImpl.getById(vo.getClassifyId());
        BeanUtils.copyProperties(vo, po);
        po.setUpdateBy(userId);
        po.setCreateBy(userId);
        po.setClassifyKey(dictClassifyPO.getKey());
        po.setClassifyName(dictClassifyPO.getName());
        po.setUpdateName(Constant.EMPTY);
        // 保存数据
        this.insert(po);
    }

    /**
     * 更新字典表
     *
     * @param vo
     * @throws BizException
     */
    public void update(DictVO vo, Long userId, String token) throws BizException {
        // 校验
        validateDictVO(vo);
        Asserts.notNull(vo.getId(),"字典表对象的主键不能为空");

        // 构造参数
        DictPO po = new DictPO();
        DictClassifyPO dictClassifyPO = dictClassifyServiceImpl.getById(vo.getClassifyId());
        BeanUtils.copyProperties(vo, po);
        po.setUpdateBy(userId);
        po.setUpdateAt(LocalDateTime.now());
        po.setClassifyKey(dictClassifyPO.getKey());
        po.setClassifyName(dictClassifyPO.getName());
        po.setUpdateName(Constant.EMPTY);
        // 保存数据
        this.update(po);
    }

    /**
     * 校验字典表vo
     *
     * @param vo
     * @throws BizException
     */
    public void validateDictVO(DictVO vo) throws BizException {
        Asserts.notNull(vo, "字典表对象");
        Asserts.notNull(vo.getClassifyId(), "字典分类外键");
        Asserts.notNull(vo.getOrderIdx(), "字典排序");
        Asserts.notNull(vo.getValue(), "字典值");
        Asserts.notNull(vo.getDisName(), "字典名称");
    }

    /**
     * 根据参数查询字典表对象
     * <p>
     * 可塞入dataNode以控制mycat选择数据库
     * </p>
     *
     * @return
     * @throws BizException
     */
    public DictPO getByParams(Map<String, Object> params, String dataNode) throws BizException {
        Asserts.notNull(params, "参数");
        try {
            if (!StringUtils.isEmpty(dataNode)) params.put("dataNode", getSQLPerfix(dataNode));
            return dictDao.getByParams(params);
        } catch (Exception e) {
            logger.error("查询失败", e);
            throw new BizException("查询失败");
        }
    }

    /**
     * 根据id参数查询字典表对象
     *
     * @return
     * @throws BizException
     */
    public DictPO getById(Long id) throws BizException {
        Asserts.notNull(id, "id");
        try {
            return getByParams(of("id", id), null);
        } catch (Exception e) {
            logger.error("查询失败", e);
            throw new BizException("查询失败");
        }
    }

    /**
     * 字典表查询dto
     *
     * @param dto
     * @param
     * @return
     * @throws BizException
     */
    public PageVO<DictVO> selectByPage(DictQueryDTO dto) throws BizException {
        Asserts.notNull(dto, "查询对象");
        Map<String, Object> params = BeanUtils.populate(dto);
        PageHelper.startPage(dto);
        return PageVO.toPageVO(findByParams(params));
    }

    /**
     * 根据主键删除字典表
     * @param dto
     *
     * @throws BizException
     */
    public void delete(IdDTO<Long> dto, Long userId) throws BizException {
        Asserts.notNull(dto,"主键");
        DictPO po = this.getById(dto.getId());
        Asserts.notNull(po, "要删除的对象");
        po.setUpdateAt(LocalDateTime.now());
        po.setUpdateBy(userId);
        delete(po);
    }

    /**
     * 根据分类id查询字典表
     *
     * @param dto
     * @param deptPath
     * @return
     * @throws BizException
     */
    public List<DictVO> selectWithClassifyId(IdDTO dto) throws BizException {
        Asserts.notNull(dto, "参数");
        Map<String, Object> params = Maps.newHashMap();
        params.put("classifyId", dto.getId());
        return findByParams(params);
    }

    /**
     * 根据id查询字典表vo
     * @param idDTO
     * @throws BizException
     */
    public DictVO getById(IdDTO<Long> idDTO) throws BizException {
        Asserts.notNull(idDTO, "id");
        DictPO po = getById(idDTO.getId());
        Asserts.check(Objects.nonNull(po), "该id不存在");
        DictVO vo = new DictVO();
        BeanUtils.copyProperties(po, vo);
        return vo;
    }

    /**
     * 根据id
     *
     * @param dto
     * @param
     * @return
     * @throws BizException
     */
    public JSONObject selectWithClassifyIds(IdsDTO dto) throws BizException {
        Asserts.notNull(dto, "参数");
        Map<String, Object> params = Maps.newHashMap();
        params.put("classifyIds", dto.getIds());
        JSONObject result = new JSONObject();
        List<DictVO> vos = findByParams(params);
        if (CollectionUtils.isEmpty(vos)) {
            return result;
        }
        Map<Long, List<DictVO>> classifyId_vos_map
                = vos.stream().collect(Collectors.groupingBy(DictVO::getClassifyId));
        JSONObject jsonObject = (JSONObject)JSONObject.toJSON(classifyId_vos_map);
        return jsonObject;
    }


    /**
     * 根据字典表key查询字典表对象集合
     *
     * @param dto
     * @param
     * @return
     * @throws BizException
     */
    public List<DictVO> selectWithClassifyKey(DictClassifyQueryDTO dto) throws BizException {
        Asserts.notNull(dto, "查询参数");
        Map<String, Object> params = BeanUtils.populate(dto);
        return findByParams(params);
    }

    /**
     * @param dto
     * @param
     * @return
     * @throws BizException
     */
    public JSONObject selectWithClassifyKeys(DictClassifysQueryDTO dto) throws BizException {
        Asserts.notNull(dto, "参数");
        Map<String, Object> params = Maps.newHashMap();
        params.put("classifyKeys", dto.getClassifyKeys());
        JSONObject result = new JSONObject();
        List<DictVO> vos = findByParams(params);
        if (CollectionUtils.isEmpty(vos)) {
            return result;
        }
        Map<String, List<DictVO>> classifyId_vos_map
                = vos.stream().collect(Collectors.groupingBy(DictVO::getClassifyKey));
        JSONObject jsonObject = (JSONObject)JSONObject.toJSON(classifyId_vos_map);
        return jsonObject;
    }
}
